# -*- coding: utf-8 -*-

from .nuonuo import Nuonuo
from . import odoo_fields as fields
import json

import logging

_logger = logging.getLogger(__name__)


class BaseModel(object):
    @classmethod
    def value_get(cls, record):
        one = {}
        for fld, val in record.items():
            if hasattr(cls, fld):
                meta = getattr(cls, fld)
                one[meta.field_name] = meta.value_get(val)
        return one


class OdooFapiaoLine(BaseModel):
    # 开发票时, 从 odoo 来的数据, 转换为 api接口 需要的格式
    # 这是 明细行 对应 fp.fapiao.line

    line_num = fields.Char('明细行号', 'selfCode')  # 唯一标志, 用于回写
    vat_product_code = fields.Char('商品类别编码', 'goodsCode')
    product_name = fields.Char('货物或应税劳务、服务名称', 'goodsName')
    product_spec = fields.Char('规格型号', 'specType')
    product_uom = fields.Char('单位', 'unit')
    quantity = fields.Char('数量', 'num')
    price_tax_selection = fields.Selection(
        [('tax_excluded', '0'), ('tax_included', '1')],
        string="单价含税标志", field_name='withTaxFlag')

    price_unit = fields.Char('单价', 'price')
    tax_ratio = fields.Char('税率', 'taxRate')
    amount_tax = fields.Char('税', 'tax')
    amount_untaxed = fields.Char('不含税小记', 'taxExcludedAmount')
    amount_total = fields.Char('含税小记', 'taxIncludedAmount')

    # invoiceLineProperty ?


class OdooFapiao(BaseModel):
    # 开发票时, 从 odoo 来的数据, 转换为 API接口 需要的格式
    # 对应 fp.fapiao

    order_num = fields.Char('订单号', 'orderNo')  # 是唯一标志, 回写 fp.fapiao 时 以此查询
    date_order = fields.Datetime('订单日期', 'invoiceDate')
    type = fields.Selection(selection=[
        ('out_invoice', '1'),
        ('out_refund', '2'),
    ], string="开票类型", field_name='invoiceType')

    invoice_type = fields.Selection(selection=[
        ('vat_special', 's'),
        ('vat_general', 'c'),
        ('vat_general_e', 'p'),
        ('vat_special_e', 'b'),
    ], string="发票种类", field_name='invoiceLine')

    buyer_name = fields.Char('购方名称', 'buyerName')
    buyer_tin = fields.Char('购方税号', 'buyerTaxNum')
    buyer_phone = fields.Char('购方电话', 'buyerTel')
    buyer_address = fields.Char('购方地址', 'buyerAddress')
    buyer_bank_account = fields.Char('购方开户行及账户', 'buyerAccount')

    saler_name = fields.Char('销方名称', 'salerName')
    saler_tin = fields.Char('销方税号', 'salerTaxNum')
    saler_phone = fields.Char('销方电话', 'salerTel')
    saler_address = fields.Char('销方地址', 'salerAddress')
    saler_bank_account = fields.Char('销方开户行及账户', 'salerAccount')

    payee_name = fields.Char('收款人', 'payee')
    checker_name = fields.Char('复核', 'checker')
    drawer_name = fields.Char('开票人', 'clerk')

    note = fields.Char('备注', 'remark')
    line_ids = fields.One2many(OdooFapiaoLine, '明细行', 'invoiceDetail')

    taxmachine_code = fields.Char('税控设备', 'machineCode')

    @classmethod
    def prepare_create(cls, record):
        order = cls.value_get(record)
        content = {'order': order}
        return content


class NuonuoFapiaoLine(BaseModel):
    # 开发票成功后, 读取诺诺发票数据, 写入 odoo 前. 转换为 odoo 需要的格式
    # 对应 fp.fapiao.line

    itemSelfCode = fields.Char('明细行号', 'line_num')  # 关键字段, 以此查询明细行

    # isIncludeTax = fields.Float('单价含税标记', 'price_with_tax')
    # itemPrice = fields.Float('单价', 'price')
    # itemAmount = fields.Float('金额', 'amount')

    itemNum = fields.Float('数量', 'quantity')
    itemTaxRate = fields.Float('税率', 'tax_ratio')
    itemTaxAmount = fields.Float('税', 'amount_tax')

    itemPriceUnit = fields.Float('含税单价', 'price_unit')
    itemPriceUntax = fields.Float('不含税单价', 'price_untax')

    itemAmountTotal = fields.Float('含税金额', 'amount_total')
    itemUntaxAmount = fields.Float('不含税金额', 'amount_untaxed')

    @classmethod
    def value_get(cls, record):
        isIncludeTax = record.get('isIncludeTax')

        itemAmount = record.get('itemAmount', 0)
        itemAmount = float(itemAmount)

        itemTaxAmount = record.get('itemTaxAmount')
        itemTaxAmount = float(itemTaxAmount)

        itemNum = record.get('itemNum')
        itemNum = float(itemNum)
        # itemTaxRate = record.get('itemTaxRate')
        # itemTaxRate = float(itemTaxRate)

        if isIncludeTax:
            itemAmountTotal = round(itemAmount, 2)
            itemUntaxAmount = itemAmountTotal - itemTaxAmount
        else:
            itemAmountTotal = itemUntaxAmount + itemTaxAmount
            itemUntaxAmount = itemAmount

        itemAmountTotal = round(itemAmountTotal, 2)
        itemUntaxAmount = round(itemUntaxAmount, 2)

        # record['itemTaxAmount'] = itemTaxAmount  # tax
        record['itemUntaxAmount'] = itemUntaxAmount  # 不含税金额
        record['itemAmountTotal'] = itemAmountTotal  # 含税金额

        itemPriceUnit = itemAmountTotal / itemNum
        itemPriceUnit = round(itemPriceUnit, 2)
        itemPriceUntax = itemUntaxAmount / itemNum
        itemPriceUntax = round(itemPriceUntax, 8)

        record['itemPriceUnit'] = itemPriceUnit  # 含税单价
        record['itemPriceUntax'] = itemPriceUntax  # 不含税单价

        one = super().value_get(record)

        one['tax_ratio'] = one['tax_ratio'] * 100
        return one


class NuonuoFapiao(BaseModel):
    # 开发票成功后, 读取诺诺发票数据, 写入 odoo 前. 转换为 odoo 需要的格式
    # 对应 fp.fapiao

    orderNo = fields.Char('订单号', 'order_num')  # 唯一标志, 回写odoo时 以此查询
    serialNo = fields.Char('诺诺流水号', 'serial_num')
    invoiceDate = fields.TimeInteger('开票时间', 'time_fapiao')

    # pdfUrl = fields.PdfURL('pdf Url', 'attachment_id')  # pdf 文件, 写入附件
    # 特殊字段, 单独处理

    invoiceCode = fields.Char('发票代码', 'type_code')
    invoiceNo = fields.Char('发票号码', 'code')
    checkCode = fields.Char('校验码', 'check_code')

    machineCode = fields.Char('机器编号', 'taxmachine_code')
    checker = fields.Char('复核', 'checker_name')
    payee = fields.Char('收款人', 'payee_name')
    clerk = fields.Char('开票人', 'drawer_name')

    exTaxAmount = fields.Float('不含税金额', 'amount_untaxed')
    taxAmount = fields.Float('税额', 'amount_tax')
    orderAmount = fields.Float('含税金额', 'amount_total')
    invoiceItems = fields.One2many(NuonuoFapiaoLine, '明细行', 'line_ids')

    status = fields.Selection(selection=[
        ('2', 'done'),  # 开票成功
        ('20', 'doing'),  # 开票中
        ('21', 'signing'),  # 开票成功签章中
        ('22', 'doerror'),  # 开票失败
        ('24', 'signerror'),  # 开票成功签章失败
        ('3', 'be_invalid'),  # 已作废
        ('31', 'being_invalid'),  # 作废中
    ], string="状态", field_name='api_status')

    statusMsg = fields.Char('状态消息', 'api_status_msg')
    failCause = fields.Char('失败原因', 'api_fail_cause')

    @classmethod
    def value_get(cls, record):
        one = super().value_get(record)
        orderNo = record['orderNo']
        meta = fields.PdfURL('pdf Url', 'attachment_id')
        one[meta.field_name] = meta.value_get(record['pdfUrl'], orderNo)
        one['date_fapiao'] = one['time_fapiao'][0:10]
        return one

    @classmethod
    def after_read(cls, records):
        return [cls.value_get(record) for record in records]


class OdooNuonuo(Nuonuo):
    def create(self, record):
        content = OdooFapiao.prepare_create(record)

        # todo: loggin ...
        response = self.requestBillingNew(content)
        # {"code":"E0000","describe":"开票提交成功","result":{"invoiceSerialNum":"22072813402302591953"}}
        # todo: loggin ...

        response = json.loads(response)
        code = response['code']

        if code != 'E0000':
            return {'error': response}

        result = response['result']
        invoiceSerialNum = result['invoiceSerialNum']
        return {'result': invoiceSerialNum}

    def read(self, invoiceSerialNum_list):
        content = {
            "isOfferInvoiceDetail": "1",
            "orderNos": [],
            "serialNos": invoiceSerialNum_list
        }

        response = self.queryInvoiceResult(content)
        response = json.loads(response)

        code = response['code']
        if code != 'E0000':
            return {'error': response}

        records = response['result']

        _logger.info('read fapiao, %s',  records)

        records2 = NuonuoFapiao.after_read(records)
        return {'result': records2}

    def invalid(self, invoiceSerialNum, invoiceCode, invoiceNo):
        content = {
            "invoiceId": invoiceSerialNum,
            "invoiceCode": invoiceCode,
            "invoiceNo": invoiceNo
        }

        # _logger.info('OdooNuonuo invalid:%s,', content)

        # return {'error': 'test debug'}

        response = self.invoiceCancellation(content)
        response = json.loads(response)

        code = response['code']
        if code != 'E0000':
            return {'error': response}

        result = response['result']
        invoiceId = result['invoiceId']
        return {'result': invoiceId}

    def print_batch(self, data):
        content = {
            "outInvoicePrintRequests": data,
        }

        _logger.info('OdooNuonuo print_batch:%s,', content)

        # return {'error': 'test debug'}

        response = self.invoicePrintBatch(content)
        response = json.loads(response)

        _logger.info('OdooNuonuo print_batch:%s,', response)

        code = response['code']
        if code != 'E0000':
            return {'error': response}

        result = response['result']
        batchId = result['batchId']
        return {'result': batchId}


##########
##########
##########


def _bak_for_read():

    records = [
        {
            "orderNo": "20220729130924795004",

            "createTime": 1659071365000,  # 开票时间
            "updateTime": 1659071365000,
            "serialNo": "22072913092503175510",
            "status": "20",
            "statusMsg": "开票中",
            "failCause": "",
            "deptId": "",
            "extensionNumber": "0",
            "terminalNumber": "",
            "clerkId": "",
            "phone": "",
            "notifyEmail": "",
            "proxyInvoiceFlag": "0",

            "imgUrls": "",
            "ofdUrl": "",
            "pdfUrl": "https://inv.jss.com.cn/fp/6tAfp_OGN9HugJKFWKaMuTAQlsVWYd68D1iKf-WdoqFurGeCecPqG2uvWyzMZVevFECOU1TDWU-uOKQxjnAfRw.pdf",
            # "pdfUrl": "",  # pdf 链接地址. 下载后 存本地
            "pictureUrl": "",

            "invoiceType": "1",
            "invoiceKind": "增值税电子普通发票",
            "invoiceDate": 1452659400000,

            "oldInvoiceCode": "",
            "oldInvoiceNo": "",

            "productOilFlag": 0,
            "specificFactor": 0,


            "payee": "李四",
            "checker": "王五",
            "clerk": "张三",
            "remark": "备注信息",

            "payerName": "某某公司",
            "payerTaxNo": "TAXNO123456789",
            "address": "杭州市",
            "bankAccount": "中国工商银行 111111111111",
            "telephone": "0571-88888888",

            "saleName": "北京测试税号",
            "salerAccount": "民生银行 123",
            "salerAddress": "北京海淀",
            "salerTaxNum": "110101999999707",
            "salerTel": "010-81234567",

            "invoiceNo": "",
            "invoiceCode": "",

            "exTaxAmount": "88.50",  # 汇总值 存本地
            "taxAmount": "11.50",
            "orderAmount": "100.00",


            "listFlag": "0",
            "listName": "",

            "invoiceItems": [
                {
                    "itemSelfCode": "itemline_id_1",
                    "itemPrice": "10.000000000000000000",
                    "itemNum": "10.000000000000000000",
                    "itemTaxRate": "0.13",
                    "itemAmount": "100.00",
                    "itemTaxAmount": "11.50",

                    "itemCodeAbb": "计算机外部设备",
                    "itemCode": "1090511030000000000",
                    "itemName": "电脑",
                    "itemSpec": "y460",
                    "itemUnit": "",

                    "deduction": "0.00",
                    "isIncludeTax": "true",
                    "invoiceLineProperty": "0",
                    "zeroRateFlag": "",
                    "favouredPolicyName": "",
                    "favouredPolicyFlag": "0"

                }
            ]
        }]


def _bak_for_read2():
    res = {
        "code": "E0000", "describe": "获取成功",
        "result": [
            {
                # 唯一标识,
                "orderNo": "20170105120207971597",  # 订单编号

                # api 接口 专用
                "createTime": 1658986824000,
                "updateTime": 1658986849000,
                "serialNo": "22072813402302591953",  # 发票请求流水号
                "status": "2",
                # 2 完成, 22 失败, 24 签章失败 3 发已经作废
                # 20 开票中, 21 开票成功签章中 31 作废中
                "statusMsg": "开票完成（最终状态）",
                "failCause": "",
                # 接口 用参数
                "extensionNumber": "0",
                "terminalNumber": "",
                "deptId": "",
                "clerkId": "",
                "phone": "15858585858",
                "notifyEmail": "test@xx.com",
                # 代开标志
                "proxyInvoiceFlag": "0",



                "imgUrls": "https://inv.jss.com.cn/fp/6tAfp_OGN9HugJKFWKaMufGo7kNCoGGT3jcA-dzKLJ2BglqXqYb8m3un8qUb3M_6sEs5FwG20CCSZUwX4efR2A.jpg",
                "ofdUrl": "",
                "pdfUrl": "https://inv.jss.com.cn/fp/6tAfp_OGN9HugJKFWKaMuTAQlsVWYd68D1iKf-WdoqFurGeCecPqG2uvWyzMZVevFECOU1TDWU-uOKQxjnAfRw.pdf",
                "pictureUrl": "nnfp.jss.com.cn/uK58qLvK-hOZLaG",


                "invoiceType": "1",  # 开票类型
                "invoiceDate": 1452659400000,
                "invoiceTime": 1658986818000,
                "invoiceKind": "增值税电子普通发票",


                # 红票用数据
                "oldInvoiceCode": "",
                "oldInvoiceNo": "",

                # 成品油标志
                "productOilFlag": 0,
                "specificFactor": 0,

                "qrCode": "01,10,011002100801,68755680,0.88,20220728,74265727323464402719,F93E,",
                "machineCode": "661101410710",
                "cipherText": "/287/84-55+/40/->*4169>78/05-834>*25/5>29759185715--83<2*6*729990+55+9004-/808>-/38+754734>*25/5>29759183<91",

                "payee": "李四",
                "checker": "王五",
                "clerk": "张三",
                "remark": "备注信息",

                "payerName": "企业名称/个人",
                "payerTaxNo": "",
                "address": "杭州市",
                "bankAccount": "中国工商银行 111111111111",
                "telephone": "0571-88888888",

                "saleName": "北京测试税号",
                "salerTaxNum": "110101999999707",
                "salerTel": "0571-77777777",
                "salerAddress": "北京海淀",
                "salerAccount": "民生银行 123",

                "invoiceCode": "011002100801",
                "invoiceNo": "68755680",
                "checkCode": "74265727323464402719",

                "exTaxAmount": "0.88",  # 不含税金额
                "taxAmount": "0.12",  # 税额
                "orderAmount": "1.00",

                # 明细行
                "listFlag": "0",
                "listName": "",
                "invoiceItems": [
                    {
                        "itemCode": "1090511030000000000",
                        "itemSelfCode": "130005426000000000",
                        "itemSpec": "y460",
                        "itemName": "电脑",
                        "itemCodeAbb": "计算机外部设备",
                        "itemUnit": "台",
                        "itemPrice": "1.000000000000000000",
                        "itemTaxRate": "0.13",
                        "itemNum": "1.000000000000000000",
                        "itemAmount": "1.00",
                        "isIncludeTax": "true",
                        "itemTaxAmount": "0.12",

                        "invoiceLineProperty": "0",
                        "zeroRateFlag": "",
                        "favouredPolicyName": "",
                        "favouredPolicyFlag": "0",
                        "deduction": "0.00",

                    }
                ]
            }
        ]
    }

##########
##########
##########


def _bak_for_create():
    # 订单号 不能重复, 每张发票唯一
    orderNo = now_get()

    # 订单信息
    orderInfo = {
        "orderNo": orderNo,  # 订单号
        "invoiceDate": "2016-01-13 12:30:00",  # 订单时间
        "invoiceType": "1",  # 开票类型 蓝票/红票
        "invoiceLine": "p",  # 发票种类 普票/专票/电子普票
        # "specificFactor": "0",  # 特定要素
        # "proxyInvoiceFlag": "0", #待开标志
    }

    # 开票方信息, 存在 odoo 系统中
    saler = {
        # 卖方名称无需提供, nuonuo系统中已经有了
        "salerTaxNum": tin,
        "salerTel": "010-81234567",
        "salerAddress": "北京海淀",
        "salerAccount": "民生银行 123",
    }

    # 买方信息, 在Fapiao中
    buyer = {
        "buyerName": "某某公司",
        "buyerTaxNum": "TAXNO123456789",
        "buyerTel": "0571-88888888",
        "buyerAddress": "杭州市",
        "buyerAccount": "中国工商银行 111111111111",
    }

    # 开票员等信息, 在Fapiao中
    users = {
        "checker": "王五",
        "payee": "李四",
        "clerk": "张三",
    }

    # 诺诺系统专用信息
    nuonuoInfo = {
        # "departmentId": "9F7E9439CA8B4C60A2FFF3EA3290B088",
        # "clerkId": "",
        # "callBackUrl": "http:127.0.0.1/invoice/callback/",
        # "extensionNumber": "0",
        # terminalNumber: "", # 终端号
        # "machineCode": "661288888888", # 机器编号(12位盘号)
        # "hiddenBmbbbh": "0",
    }

    # 全电发票专用信息
    QuanDianFapaio = {
        # "buyerManagerName": "张三",
        # "managerCardNo": "",
        # "managerCardType": "201",
        # "additionalElementName": "测试模版",
        # "additionalElementList": {
        #     "elementValue": "信息值", "elementType": "信息类型", "elementName": "信息名称"
        # },

    }

    # 红票信息
    redInfo = {
        "invoiceCode": "125999915630",  # 对应蓝票代码
        "invoiceNum": "00130865",  # 对应蓝票号码
        "redReason": "1",  # 冲红原因
        "billInfoNo": "1403011904008472",  # 专票冲红必填
    }

    controlInfo = {
        # 信息推送相关
        # "pushMode": "1",
        # "buyerPhone": "15858585858",  #
        # "email": "test@xx.com",

        # 发票类型为 c/f时, 普票纸质/收购发票纸质, 才用
        # "nextInvoiceNum": "12003133",
        # "nextInvoiceCode": "330112300122",

    }

    remark = {
        "remark": "备注信息",  # 备注栏
    }

    linesInfo = {
        # 明细行太多时, 需要用清单
        # "listFlag": "0",
        # "listName": "详见销货清单",
        'invoiceDetail': [
            {

                "goodsName": "电脑",
                "goodsCode": "1090511030000000000",
                "selfCode": "130005426000000000",

                "specType": "y460",
                "num": "1",
                "unit": "台",

                "withTaxFlag": "1",
                "price": "1",

                "taxRate": "0.13",
                "tax": "0.12",
                "taxExcludedAmount": "0.88",
                "taxIncludedAmount": "1",

                "invoiceLineProperty": "0",
                "favouredPolicyFlag": "0",
                "favouredPolicyName": "0",
                "deduction": "0",
                "zeroRateFlag": "0",
            }
        ]
    }

    order = {}

    order.update(buyer)
    order.update(saler)
    order.update(users)
    order.update(remark)
    order.update(orderInfo)
    order.update(linesInfo)

    otherFapiaoInfo = {
        "vehicleFlag": "1",
        "vehicleInfo": {
            "taxOfficeCode": "13399000", "manufacturerName": "华晨宝马汽车生产有限公司", "importCerNum": "",
            "certificate": "WDL042613263551", "engineNum": "10111011111", "taxOfficeName": "杭州税务", "brandModel": "宝马3系", "productOrigin": "北京",
            "vehicleCode": "LHGK43284342384234", "maxCapacity": "5",
            "intactCerNum": "",
            "tonnage": "2",
            "insOddNum": "",
            "idNumOrgCode": "9114010034683511XD", "vehicleType": "轿车"
        },
        "secondHandCarInfo": {
            "organizeType": "1",
            "vehicleManagementName": "杭州",
            "sellerPhone": "13888888888",
            "sellerName": "张三",
            "brandModel": "宝马3系",
            "vehicleCode": "LHGK43284342384234",
            "licenseNumber": "浙A12345", "registerCertNo": "330022123321", "sellerAddress": "杭州文一路888号", "vehicleType": "轿车",
            "intactCerNum": "",
            "sellerTaxnum": "330100199001010000"
        },


    }

    content = {
        'order': order
    }
